/*! 
 * jquery.ux - v 1.0.0 - http://jquery-ux.com/
 * Copyright (c) 2010 Michael Helgeson, Three Dub Media
 * Open Source MIT License - http://jquery-ux.com/license 
 */
// Created: 2008-01-31
// Updated: 2010-06-11
// REQUIRES: jquery 1.4

;(function( $ ){ // confine scope
		   
/**
 * The UX Plugin Factory...
 *   $.ux( "plugin", {} ); // install plugin
 *   $.ux( "plugin", false ); // remove plugin
 *   $.ux( "plugin.method" ); // call method on every plugin instance
 *   $.ux( ".method" ); // call method on every ux plugin instance
 */
$.ux = function( plugin, config ){
	
	// "new" is used, instantly return the instance
	if ( this instanceof $.ux ) 
		return;
	
	// the first argument must ALWAYS be a string
	if ( typeof plugin != "string" || !plugin.length ) 
		return false;
	
	// if the first arg contains a dot, GLOBAL METHOD 
	if ( plugin.indexOf(".") > -1 )
		return $.fn.ux.apply( this, arguments );
	
	// remove a ux plugin
	if ( $.ux.plugins[ plugin ] && config === false ){
		// destroy any existing instances
		$.ux( plugin +".destroy");
		 // remove static method
		delete $[ plugin ];
		// remove instance method
		delete $.fn[ plugin ]; 
		// remove custom selector
		delete $.expr[':'][ plugin ];
		// remove from Plugin cache
		delete $.ux.plugins[ plugin ];
		delete $.ux[ plugin ];
		return true;
	}
	
	// require config, make sure plugin does not exist, and name is safe...
	if ( !config || $.ux.plugins[ plugin ] || $.ux[ plugin ] ) 
		return false;
	
	// create and store a new factory instance
	var Plugin = $.ux.plugins[ plugin ] = new $.ux();
	
	// initialize the ux plugin properties
	$.extend( Plugin, {
		id: ".ux-"+ plugin +"-",
		name: plugin,
		index: 1,
		cache: {},
		exposed: {},
		config: config,
		settings: { 
			defaults: config.defaults || {} 
		}
	});	
	
	// install the plugin interface 
	
	/**
	 * The Plugin Constructor...
	 *   new $.ux.plugin( element, options ); // plugin instance
	 */
	$.ux[ plugin ] = function( elem, opts ){
		return this instanceof $.ux[ plugin ] ? 
			Plugin.construct.call( this, elem, opts ) :	
			new $.ux[ plugin ]( elem, opts );
	};
	
	/**
	 * The Plugin jQuery Method...
	 *   $( selector ).plugin( options ); // plugin instances
	 */
	$.fn[ plugin ] = function(){
		return Plugin.invoke.call( this, Plugin, ([]).slice.call( arguments, 0 ) );
	};
	
	/**
	 * The Plugin Function...
	 *   $.plugin( {} ); // set plugin defaults
	 *   $.plugin( "label", {} ); // set plugin setting 
	 */
	$[ plugin ] = function(){
		return Plugin.setting.apply( Plugin, arguments );
	};
	
	/**
	 * The Plugin Psuedo Selector
	 *   $(":plugin"); // match any elements that are using plugin
	 */
	$.expr[':'][ plugin ] = function( a ){
		return !!Plugin.find.apply( Plugin, arguments );
	};
	
	// static version number property
	$[ plugin ].version = $.ux[ plugin ].version = config.version;	
	
	// set plugin instance methods ( inheriting from "$.ux.fn" )
	$.ux[ plugin ].prototype = $.ux[ plugin ].fn = new Plugin.proto( config.methods, Plugin );
	
	// expose public methods, false to prevent 
	if ( config.expose !== false ){ 
		// three methods are automatically exposed
		config.expose = ( config.expose || "" ) + " option enable disable destroy";
		// iterate the "expose" configuration
		$.each( config.expose.split(/\s+/), function( i, method ){ 
			// verify and remember allowed public methods
			Plugin.exposed[ method ] = !!( method && $.ux[ plugin ].prototype[ method ] );
		});
	}
	
	return Plugin;
};

// track all plugins
$.ux.plugins = {};

// factory methods
$.ux.prototype = {
	// the jquery method that invokes plugins	
	invoke: function( Plugin, args ){
		// local refs, slice the arguments into an actual array
		var setting = {}, opts;
		// if the arg is a custom setting...
		if ( Plugin.settings[ args[0] ] ){
			setting = Plugin.settings[ args[0] ];
			args.shift();
		}
		// configure the plugin
		opts = Plugin.config.prepare ? Plugin.config.prepare.apply( this, args ) : args[0];
		// false to cancel initialization of the entire collection
		if ( opts === false ) 
			return this;
		// inherit default plugin options...
		opts = $.extend({}, Plugin.settings.defaults, setting, typeof opts == "object" ? opts : {} );
		// iterate the entire collection
		return this.each( function( i, node ){;
			// make sure there is no instance already
			if ( !Plugin.find( node ) ) 
				// instaniate new plugin...
				new $.ux[ Plugin.name ]( node, opts );
		});
	},
	// get and set plugin settings and defaults
	setting: function( arg ){
		// allow numeric and string identifiers for the settings
		var key = ( typeof arg == "string" || typeof arg == "number" ) ? arg : "defaults", 
		// make sure the setting exists, or create it
		setting = ( this.settings[ key ] = this.settings[ key ] || {} ), 
		// slice all of the arguments
		args = ([]).slice.call( arguments, key == arg ? 1 : 0 );
		// extend and return the settings
		return $.extend.apply({}, ([ setting ]).concat( args ) );
	},
	// find the stored instance in data cache (without polution)...
	find: function( elem ){
		var uxid = ( $.cache[ ( elem[ $.expando ] || 0 ) ] || {} )[ this.id ];
		return ( this.cache[ uxid || 0 ] || {} ).instance;
	},
	// verify argument is a public method...
	allow: function( method ){
		return typeof method == "string" && this.exposed[ method ];
	},	
	// safely passes along "$.ux.fn" prototype
	proto: function( obj, Plugin ){ 
		$.extend( this, obj || {} ); // mixin config.methods 
		this.constructor = $.ux[ Plugin.name ]; // plugin constructor
		this.ux = Plugin; // plugin instance "super" property
	},	
	// inside plugin constructor
	construct: function( elem, opts ){
		if ( !elem && !opts ) return; // instant instance
		// a unique instance identifier...
		this.uxid = this.ux.id + ( this.ux.index++ );
		// pull in the arguments
		this.element = elem;
		this.options = opts;		
		// cache the instance and element
		this.ux.cache[ this.uxid ] = { instance:this, element:elem };
		// custom create function...
		if ( this.ux.config.create && this.ux.config.create.apply( this, arguments )===false )
			return ( delete this.ux.cache[ this.uxid ] ); // initialization was suppressed...
		// store the cache index value
		$.data( elem, this.ux.id, this.uxid );
		// automatically bind any passed callbacks
		$.each( opts.events || [], $.proxy( this, "observe") );
	}
};

// plugin methods
$.ux.fn = $.ux.prototype.proto.prototype = {
	/* proxy: function( method ){
		return $.proxy( this, method ); // << jquery 1.4
		}, */
	classify: function( name ){
		var classes = this.options.classes || {},
		root = this.options.classroot || "ux-"+ this.ux.name;		
		return classes[ name ] || root +( name ? "-"+ name : "" );
	},
	publish: function( type ){
		var event = new $.Event( type +":"+ this.ux.name ); 
		event.target = this.element;
		arguments[ 0 ] = event; // inject event object
		$.event.handle.apply( event.target, arguments );
		return event; 
	},
	observe: function( type, handler ){
		$( this.element ).bind( type +":"+ this.ux.name, handler );
	},
	unobserve: function( type, handler ){
		$( this.element ).unbind( type +":"+ this.ux.name, handler );
	},	
	disabled: false,
	enable: function(){
		var fn = this.ux.config.disable;
		if ( fn && fn.call( this, false ) === false ) 
			return;
		this.disabled = false;	
	}, 
	disable: function(){
		var fn = this.ux.config.disable;
		if ( fn && fn.call( this, true ) === false )
			return;
		this.disabled = true;	
	},
	// get/set instance options
	option: function( arg, value ){
		var argType = ( typeof arg ), undefined;
		if ( argType == "string" )
			if ( value === undefined )
				return this.options[ arg ];
			else this.options[ arg ] = value;
		// donate props of a hash object	
		else if ( argType == "object" )
			$.extend( this.options, arg );
	},
	destroy: function(){
		var self = this, elem, 
		fn = self.ux.config.destroy;
		// custom destroy function...
		if ( fn && fn.call( self ) === false ) 
			return;
		// automaticaly unbind any passed callbacks	
		$.each( this.options.events || [], $.proxy( this, "unobserve") );
		// local instance tracking...
		if ( elem = self.element )
			$.removeData( elem, this.ux.name );
		$.removeData( self );	
		// global instance tracking
		delete self.ux.cache[ self.uxid ];
		// self destruct...
		setTimeout( function(){
			for ( var attr in self ) 
				delete self[ attr ];
			self = elem = null;
		}, 100 );
	}
};
	
/**
 * The UX jQuery Method...
 *   // call method on every plugin instance in collection
 *   $( selector ).ux( "plugin.method" ); 
 *   // call method on every ux plugin instance in collection
 *   $( selector ).ux( ".method" ); 
 */
$.fn.ux = function( arg ){
	// validate args...
	if ( arg.indexOf( "." ) < 0 ) return this;
	else arg = arg.split('.'); // "plugin.method"
	// local refs
	var returned, instance, undefined,
	plugin = arg[0], method = arg[1], 
	args = ([]).slice.call( arguments, 1 ),
	$this = this.jquery ? this.filter(":"+( plugin || "ux" )) : false;
	// specific or generic: ONE PLUGIN or ALL PLUGINS	
	$.each( plugin.length ? [ $.ux.plugins[ plugin ] ] : $.ux.plugins, function( i, Plugin ){
		// plugin exists and method is exposed
		if ( Plugin && Plugin.allow( method ) ){
			// iterate all jquery collection or all elements
			$.each( $this || Plugin.cache, function( i, val ){
				// found a valid instance
				if ( instance = !$this && val ? val.instance : Plugin.find( val ) ) 
					// call the method with arguments
					returned = instance[ method ].apply( instance, args );
				// break loop if a value is returned (in $this mode)
				return $this ? ( returned === undefined ) : true;
			});
		}
		// break loop if a value is returned (in $this mode)
		return $this ? ( returned === undefined ) : true;	
	});
	return returned === undefined ? this : returned;
};	
	
/**
 * The UX Psuedo Selector...
 *   $(":ux"); // match any elements that are using a ux plugin
 */	
/******************************************************************************/
// $(":ux"); // jquery pseudo selector...
$.expr[":"]["ux"] = function( elem ){
	var key, data = $.cache[ ( elem[ $.expando ] || 0 ) ] || {};
	for ( key in data ) 
		if ( !key.indexOf(".ux-") ) 
			return true;
	return false;
};
/******************************************************************************/
})( jQuery ); // secure the $ jQuery alias
// FFFF8141 BF7DA155 BD55A155 FD0581FF FF81A0BF AA85AABD AA85BEFD 8281FFFF 